package com.syni.mdd.yhd.common.all.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.syni.mdd.sjb.common.component.utils.common.utils.AppConfig;
import com.syni.mdd.sjb.common.component.utils.common.utils.ParamsMap;
import com.syni.mdd.sjb.common.component.utils.common.utils.ResultMapHelper;
import com.syni.mdd.yhd.common.all.constants.Constants;
import com.syni.mdd.yhd.common.all.constants.ResultCode;
import com.syni.mdd.yhd.common.all.constants.ResultMsg;
import com.syni.mdd.yhd.common.all.dto.video.SearchVideoDto;
import com.syni.mdd.yhd.common.all.entity.BmsBusiness;
import com.syni.mdd.yhd.common.all.entity.BmsDxGroupBuy;
import com.syni.mdd.yhd.common.all.entity.BmsVideo;
import com.syni.mdd.yhd.common.all.service.*;
import com.syni.mdd.yhd.common.all.service.search.BmsSearchService;
import com.syni.mdd.yhd.common.all.utils.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @className
 * @description TOO
 * @Author cfx
 * @DATE 2019/4/9 12:04
 * @VERSION 1.0
 **/
@Service
public class BmsSearchServiceImpl implements BmsSearchService {
    private Logger logger = LoggerFactory.getLogger(getClass());
    //视频搜索
    final int videoCode = 1;
    //店铺搜索
    final int businessCode = 2;
    //团购搜索
    final int groupBuyCode = 3;
    //
    //视频店铺（全局）搜索
    final int businessVideoCode = 0;
    @Autowired
    BmsVideoService bmsVideoService;

    @Autowired
    BmsBusinessService bmsBusinessService;

    @Autowired
    BmsDxGroupBuyService bmsDxGroupBuyService;

    @Autowired
    BmsSearchLogService bmsSearchLogService;

    @Autowired
    RedisTemplate redisTemplate;

    /**
     * @Description 视频搜索联动
     * @Author: cfx
     * @Date: 2019/9/25
     */
    @Override
    public Map<String, Object> match(ParamsMap paramsMap) {
        Map<String,Object> resultMap = new HashMap<>();
        String searchText = paramsMap.getStringSimple("searchText");
        if(StringUtils.isBlank(searchText)){
            return ResultMapHelper.success(resultMap,ResultMsg.MSG_GET_SUCCESS);
        }
        //纬度
        String latitude = paramsMap.getString("latitude");
        //经度
        String longitude = paramsMap.getString("longitude");
        //条数
        Integer pageSize = paramsMap.getInteger("pageSize");
        //页数
        Integer pageNum = paramsMap.getInteger("pageNum");
        Map<String, Object> conditionMap = new HashMap<>();
        //Set<Integer> videoIds = bmsVideoService.findVideoByNameAndDesc(searchText);
        resultMap.put("bmsVideosNum",  this.getVideoNumByAlgorithm(searchText));
        /*Set<Integer> groupIds = bmsDxGroupBuyService.findGroupBuyByGroupName(searchText);
        Set<Integer> businessGroupIds = bmsDxGroupBuyService.findGroupBuyByVendorName(searchText);
        gIds.addAll(groupIds);
        gIds.addAll(businessGroupIds);*/
        Set<Integer> gIds = bmsDxGroupBuyService.findGroupBuyByGroupOrVendorName(searchText);
        resultMap.put("groupBuyNum", gIds.size());
        Long businessSize = 0L;
        conditionMap.clear();
        //条件在这里
        conditionMap.put("isDelete", Constants.COMMON_FLAG_FALSE_INT);
        conditionMap.put("isUnload", Constants.COMMON_FLAG_FALSE_INT);
        conditionMap.put("vendorName_LIKE", searchText);
        List<BmsBusiness> bmsBusinesses = new LinkedList<>();
        Date nowTime = new Date();
        if(StringUtils.isNotBlank(latitude) && StringUtils.isNotBlank(longitude)) {
            //主要进这里
            //count查询自带的
            //bmsBusinessService.test();
            businessSize = bmsBusinessService.getBaseDao().count(new SpecificationUtils(conditionMap));
            bmsBusinesses = bmsBusinessService.getVendorNameOrderByDistance(searchText,longitude,latitude,pageNum,pageSize);
            bmsBusinessService.calculatedDistance(bmsBusinesses, latitude, longitude);
        }else {
            Pageable pageable = BmsCommonService.getPageable(pageSize,pageNum, Sort.Direction.DESC,"dkTimes");
            Page<BmsBusiness> bmsBusinessPage =  bmsBusinessService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable);
            bmsBusinesses = bmsBusinessPage.getContent();
            businessSize = bmsBusinessPage.getTotalElements();
        }
        /* List<BmsBusiness> bmsBusinesses = bmsBusinessService.getBaseDao().findAll(new SpecificationUtils(conditionMap));
        bmsBusinessService.calculatedDistance(bmsBusinesses, latitude, longitude);
        bmsBusinessService.sortByDistance(bmsBusinesses);
        businessSize = bmsBusinesses.size();
        if (bmsBusinesses.size() < endIndex) {
            endIndex = bmsBusinesses.size();
        }
        if(startIndex > bmsBusinesses.size()){
            startIndex = bmsBusinesses.size();
        }
        bmsBusinesses = bmsBusinesses.subList(startIndex, endIndex);*/
        resultMap.put("bmsBusinesses", bmsBusinesses);
        resultMap.put("bmsBusinessesNum", businessSize);
        return ResultMapHelper.success(resultMap, ResultMsg.MSG_GET_SUCCESS);
    }

    private Integer getVideoNumByAlgorithm(String searchText) {
        try {
            String postUrl = AppConfig.getProperty("syniVideoSearchRecAddress") + "/searchVideoNum";
            Map<String,Object> params = new HashMap<>();
            params.put("word",searchText);
            logger.info("请求参数：" + JSON.toJSONString(params));
            logger.info("请求url : " + postUrl);
            String responseBody = RestTemplateUtils.postForEntityForJson(postUrl,params);
            if(StringUtils.isNotBlank(responseBody)){
                Map<String,Object> retMap = JSON.parseObject(responseBody);
                return Integer.parseInt(retMap.get("search_num").toString());
            }
        }catch (Exception e){
            logger.error("rpc搜索结果调用错误",e);
        }
        return bmsVideoService.findVideoByNameAndDesc(searchText).size();
    }


    @Override
    public Map<String, Object> typeMatch(ParamsMap paramsMap) {
        final int recommendNum = 10;
        //纬度
        String latitude = paramsMap.getString("latitude");
        //经度
        String longitude = paramsMap.getString("longitude");
        //搜索内容
        String searchText = paramsMap.getStringSimple("searchText");
        //条数
        Integer pageSize = paramsMap.getInteger("pageSize");
        //用户id
        String userId = paramsMap.getString("userId");
        //页数
        Integer pageNum = paramsMap.getInteger("pageNum");
        Integer searchType = paramsMap.getInteger("searchType");
        //初始化返回值
        Map<String,Object> resultMap = new HashMap<>();
        List<BmsVideo> bmsVideos = new ArrayList<>();
        List<BmsBusiness> bmsBusinesses = new ArrayList<>();
        List<BmsBusiness> recommendBmsBusiness = new LinkedList<>();
        List<BmsVideo> recommendBmsVideos = new LinkedList<>();
        List<BmsDxGroupBuy> bmsDxGroupBuys = new ArrayList<>();
        List<BmsDxGroupBuy> recommendGroupBuys = new LinkedList<>();
        Integer isLastPage = Constants.COMMON_FLAG_TRUE_INT;
        if(StringUtils.isBlank(searchText)){
            return ResultMapHelper.success(resultMap,ResultMsg.MSG_GET_SUCCESS);
        }
        Map<String,Object> conditionMap = new HashMap<>();
        this.recordHistorySearch_V2(userId,searchText,searchType);
        this.countHotSearch(searchText);
        //if()
        if(searchType == businessCode || searchType == businessVideoCode){
            conditionMap.put("isDelete",Constants.COMMON_FLAG_FALSE_INT);
            conditionMap.put("vendorName_LIKE",searchText);
            conditionMap.put("isUnload",Constants.COMMON_FLAG_FALSE_INT);
            Pageable pageable = BmsCommonService.getPageable(pageNum,pageSize,Sort.Direction.DESC,"isOpenOrder","newTime");
            Page<BmsBusiness> businessPage = bmsBusinessService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable);
            bmsBusinesses.addAll(businessPage.getContent());
            bmsBusinessService.setIsOpenCouponAndGroupBuy(bmsBusinesses);
            if(pageNum < businessPage.getTotalPages()){
                isLastPage = Constants.COMMON_FLAG_FALSE_INT;
            }
            if(bmsBusinesses.size() == Constants.COMMON_FLAG_FALSE_INT || (isLastPage == Constants.COMMON_FLAG_TRUE_INT)){
                //进行视频的推荐(推荐10条视频)
                if(bmsBusinesses.size() > 0){
                    //判断存在商家是否是同一个城市
                    Set addrCitys = new HashSet();
                    Set labelList = new HashSet();
                    for(BmsBusiness business : bmsBusinesses){
                        if(StringUtils.isNotBlank(business.getAddrCity())){
                            addrCitys.add(business.getAddrCity());
                        }
                        if(StringUtils.isNotBlank(business.getLabel())){
                            labelList.add(business.getLabel());
                        }
                    }
                    String labels = StringUtils.join(labelList,",");
                    Map<String,Object> videoConditionMap = new HashMap<>();
                    videoConditionMap.put("isUnload",Constants.COMMON_FLAG_FALSE);
                    videoConditionMap.put("vendorName_NOLIKES",searchText);
                    pageable = PageRequest.of(0,recommendNum, Sort.Direction.DESC,"newTime");
                    if(addrCitys.size() == 1){
                        //同一个城市
                        String addrCity = addrCitys.iterator().next().toString();
                        if(StringUtils.isNotBlank(labels)){
                            //有标签
                            videoConditionMap.put("addrCity",addrCity);
                            videoConditionMap.put("label_IN",labelList);
                            recommendBmsBusiness.addAll(bmsBusinessService.getBaseDao().findAll(new SpecificationUtils(videoConditionMap),pageable).getContent());
                        }
                    }else if(addrCitys.size() > 1){
                        //多个城市
                        if(StringUtils.isNotBlank(labels)){
                            //多个城市有标签
                            videoConditionMap.put("label_IN",labelList);
                            recommendBmsBusiness.addAll(bmsBusinessService.getBaseDao().findAll(new SpecificationUtils(videoConditionMap),pageable).getContent());
                        }
                    }
                }
                if(recommendBmsBusiness.size() < recommendNum){
                    bmsBusinessService.getDefaultRecommendLevel(recommendBmsBusiness);
                }
                bmsBusinessService.setIsOpenCouponAndGroupBuy(recommendBmsBusiness);
                recommendBmsBusiness = bmsBusinessService.sortByIsOpenOrder(recommendBmsBusiness);
                resultMap.put("recommendBmsBusiness",recommendBmsBusiness);
            }
        }
        //团购
        /*conditionMap.clear();
        if(searchType == groupBuyCode || (searchType == businessVideoCode && bmsBusinesses.size() == Constants.COMMON_FLAG_FALSE_INT)) {
            conditionMap.put("status",Constants.ONLINE_STATUS);
            conditionMap.put("groupName_LIKE",searchText);
            Pageable pageable = BmsCommonService.getPageable(pageNum,pageSize,Sort.Direction.DESC,"sellNum");
            Page<BmsDxGroupBuy> bmsDxGroupBuyPage = bmsDxGroupBuyService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable);
            bmsDxGroupBuys.addAll(bmsDxGroupBuyPage.getContent());
            if(pageNum < bmsDxGroupBuyPage.getTotalPages()){
                isLastPage = Constants.COMMON_FLAG_FALSE_INT;
            }
            //推荐团购
            if(bmsDxGroupBuys.size() == Constants.COMMON_FLAG_FALSE_INT || (isLastPage == Constants.COMMON_FLAG_TRUE_INT)){
                conditionMap.remove("groupName_LIKE");
                conditionMap.put("groupName_NOLIKES",searchText);
                //是否有相同标签的团购
                Set<Integer> businessIds = new HashSet<>();
                businessIds.addAll(bmsBusinessService.findBusinessByLabel(searchText));
                businessIds.addAll(bmsBusinessService.findBusinessByVendorName(searchText));
                if(businessIds.size() > 0){
                    conditionMap.put("businessId_IN",businessIds);
                }
                pageable = BmsCommonService.getPageable(1,recommendNum,Sort.Direction.DESC,"sellNum");
                recommendGroupBuys.addAll(bmsDxGroupBuyService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable).getContent());
                if(recommendGroupBuys.size() < recommendNum) {
                    conditionMap.remove("businessId_IN");
                    Set<Integer> groupBuyIds = recommendGroupBuys.stream().map(BmsDxGroupBuy::getId).collect(Collectors.toSet());
                    if(groupBuyIds.size() > 0){
                        conditionMap.put("id_NIN",groupBuyIds);
                    }
                    pageable = BmsCommonService.getPageable(1,recommendNum - recommendGroupBuys.size(),Sort.Direction.DESC,"sellNum");
                    recommendGroupBuys.addAll(bmsDxGroupBuyService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable).getContent());
                }
            }
        }*/
        //视频
        conditionMap.clear();
        if(searchType == videoCode || (searchType == businessVideoCode
                && bmsBusinesses.size() == Constants.COMMON_FLAG_FALSE_INT && bmsDxGroupBuys.size() == Constants.COMMON_FLAG_FALSE_INT)){
            SearchVideoDto searchVideoDto = null;
            Set<Integer> videoIds = new HashSet<>();
            Map<Integer,String> rpcImgUrls = new HashMap<>();
            boolean rpcResult = false;
            try {
                searchVideoDto = this.getSearchVideoByAlgorithm(searchText,pageNum,pageSize);
                if(ResultCode.CODE_NORMAL.equals(searchVideoDto.getStatus())){
                    rpcResult = true;
                    List<JSONObject> list = searchVideoDto.getResult();
                    if(list != null && list.size() > 0){
                        for(JSONObject jsonObject : list){
                            for(Map.Entry<String,Object> entry : jsonObject.entrySet()){
                                videoIds.add(Integer.parseInt(entry.getKey()));
                                rpcImgUrls.put(Integer.parseInt(entry.getKey()),entry.getValue().toString());
                            }
                        }
                    }
                }
            }catch (Exception e){
                logger.info("rpc调用错误",e);
            }
            if(rpcResult){
                if(videoIds.size() > 0){
                    conditionMap.put("id_IN",videoIds);
                    bmsVideos.addAll(bmsVideoService.getBaseDao().findAll(new SpecificationUtils(conditionMap),Sort.by(Sort.Direction.DESC,"newTime")));
                    bmsVideoService.getListPostHand(bmsVideos,latitude,longitude,userId);
                    isLastPage = searchVideoDto.getIsLastPage();
                    if(bmsVideos.size() > 0){
                        for(BmsVideo bmsVideo : bmsVideos){
                            if(rpcImgUrls.containsKey(bmsVideo.getId())){
                                bmsVideo.setCloudFileSnapshot10Url(rpcImgUrls.get(bmsVideo.getId()));
                            }
                        }
                    }
                }
            }else {
                videoIds = bmsVideoService.findVideoByNameAndDesc(searchText);
                if(videoIds.size() > 0){
                    conditionMap.put("id_IN",videoIds);
                    Pageable pageable = BmsCommonService.getPageable(pageNum,pageSize,Sort.Direction.DESC,"newTime");
                    Page<BmsVideo> bmsVideoPage = bmsVideoService.getBaseDao().findAll(new SpecificationUtils(conditionMap),pageable);
                    bmsVideos.addAll(bmsVideoPage.getContent());
                    bmsVideoService.getListPostHand(bmsVideos,latitude,longitude,userId);
                    if(pageNum < bmsVideoPage.getTotalPages()){
                        isLastPage = Constants.COMMON_FLAG_FALSE_INT;
                    }
                }
            }
            if(bmsVideos.size() == Constants.COMMON_FLAG_FALSE_INT || (isLastPage == Constants.COMMON_FLAG_TRUE_INT)){
                //进行视频的推荐(推荐10条视频)
                if(bmsVideos.size() > 0){
                    //判断存在商家是否是同一个城市
                    Set addrCitys = new HashSet();
                    Set labelList = new HashSet();
                    for(BmsVideo bmsVideo : bmsVideos){
                        if(StringUtils.isNotBlank(bmsVideo.getAddrCity())){
                            addrCitys.add(bmsVideo.getAddrCity());
                        }
                        if(StringUtils.isNotBlank(bmsVideo.getLabel())){
                            labelList.add(bmsVideo.getLabel());
                        }
                    }
                    String labels = StringUtils.join(labelList,",");
                    Map<String,Object> videoConditionMap = new HashMap<>();
                    videoConditionMap.put("isRelease",Constants.COMMON_FLAG_FALSE);
                    videoConditionMap.put("isDelete",Constants.COMMON_FLAG_FALSE);
                    videoConditionMap.put("isOff",Constants.COMMON_FLAG_FALSE);
                    Pageable pageable = PageRequest.of(0,recommendNum, Sort.Direction.DESC,"likeTimes","newTime");
                    if(videoIds.size() > 0){
                        videoConditionMap.put("id_NIN",videoIds);
                    }
                    if(addrCitys.size() > 0 && labelList.size() > 0) {
                        videoConditionMap.put("label_IN",labelList);
                        if (addrCitys.size() == 1) {
                            //同一个城市
                            String addrCity = addrCitys.iterator().next().toString();
                            if (StringUtils.isNotBlank(labels)) {
                                //有标签
                                videoConditionMap.put("addrCity", addrCity);
                                recommendBmsVideos.addAll(bmsVideoService.getBaseDao().findAll(new SpecificationUtils(videoConditionMap), pageable).getContent());
                            }
                        } else if (addrCitys.size() > 1) {
                            //多个城市
                            if (StringUtils.isNotBlank(labels)) {
                                recommendBmsVideos.addAll(bmsVideoService.getBaseDao().findAll(new SpecificationUtils(videoConditionMap), pageable).getContent());
                            }
                        }
                    }
                }
                if(recommendBmsVideos.size() < recommendNum){
                    bmsVideoService.getDefaultRecommendLevel(recommendBmsVideos);
                }
                bmsVideoService.getListPostHand(recommendBmsVideos,latitude,longitude,userId);
            }
        }
        resultMap.put("searchType",searchType);
        if(searchType == businessVideoCode){
            if(bmsBusinesses.size() > 0){
                resultMap.put("searchType",businessCode);
            }/*else if(bmsDxGroupBuys.size() > 0){
                resultMap.put("searchType",groupBuyCode);
            } */else if(bmsVideos.size() > 0){
                resultMap.put("searchType",videoCode);
            }else{
                resultMap.put("searchType",businessCode);
            }
        }
        resultMap.put("videos",bmsVideos);
        resultMap.put("isLastPage",isLastPage);
        resultMap.put("recommendBmsBusiness",recommendBmsBusiness);
        resultMap.put("recommendBmsVideos",recommendBmsVideos);
        resultMap.put("bmsBusinesses",bmsBusinesses);
        resultMap.put("groupBuys",bmsDxGroupBuys);
        resultMap.put("recommendGroupBuys",recommendGroupBuys);
        return ResultMapHelper.success(resultMap,ResultMsg.MSG_GET_SUCCESS);
    }

    public void countHotSearch(String searchText) {
        String redisKey = Constants.REDIS_KEY_PREFIX + "hostSearch";
        Integer auto_increase = 1;
        if(redisTemplate.hasKey(redisKey)){
            redisTemplate.opsForZSet().incrementScore(redisKey,searchText,auto_increase);
        }else {
            redisTemplate.opsForZSet().incrementScore(redisKey,searchText,auto_increase);
            redisTemplate.expire(redisKey,3, TimeUnit.HOURS);
        }
    }


    @Override
    public void recordHistorySearch_V2(String userId, String searchText, Integer searchType) {
        if(userId == null || userId.startsWith(BmsVideoService.visitorPrfix)) {
            return;
        }
        bmsSearchLogService.addUserSearchHistroy(Integer.parseInt(userId),searchText,searchType);
    }

    private SearchVideoDto getSearchVideoByAlgorithm(String searchText, Integer pageNum, Integer pageSize) {
        long start = System.currentTimeMillis();
        String postUrl = AppConfig.getProperty("syniVideoSearchRecAddress") + "/searchVideo";
        Map<String,Object> params = new HashMap<>();
        params.put("word",searchText);
        params.put("page_index",pageNum);
        params.put("page_size",pageSize);
        logger.info("请求参数：" + JSON.toJSONString(params));
        logger.info("请求url : " + postUrl);
        String responseBody = RestTemplateUtils.postForEntityForJson(postUrl,params);
        long end = System.currentTimeMillis();
        logger.info("耗时 ： " + (end - start) + "ms");
        if(StringUtils.isNotBlank(responseBody)){
            SearchVideoDto searchVideoDto  = JSON.parseObject(responseBody, SearchVideoDto.class);
            return searchVideoDto;
        }
        return null;
    }

}
